﻿using System;
using System.Collections.Generic;
using TheDarkKnight;
using TheDarkKnight.DynamicSpwanModel;
using TheDarkKnight.MeshFactory;
using UnityEngine;

public class AutoCreateTunnel : MonoBehaviour
{
    [Range(0, 20)]
    public float SphereSize = 1;

    [Header("细分力度")]
    [Range(0, 100)]
    public int Segment = 3;

    public Renderer TunnelRender;

    [Header("贴图模式")]
    public TextureType TextureModel;

    public Transform PathRoot;
    [Header("模型模板数据")]
    public TempletObjectBase TemplteMesh;

    [Header("材质")]
    private Material SurfaceMat;

    [Header("前后遮罩材质")]
    private Material SectionMat;

    [HideInInspector]
    public List<Transform> m_PathList;

    [HideInInspector]
    public List<Transform> m_BezierList;

    [HideInInspector]
    public List<Vector3> m_CopyPosList;

    [HideInInspector]
    public MeshPlus SpwanTunnelMesh;

    [HideInInspector]
    public GameObject SpwanTunnelGB;

    private float m_BezierLength = 0;

    public DynamicModelLibrary.CurveModel CurveModel;

    [Header("上一段曲线斜率")]
    public Vector3 LastGradient;

    [Header("下一段曲线斜率")]
    public Vector3 NextGradient;

    public enum TextureType { 
        
        Tile,//普通平铺模式
        Texture//贴图模式
    }

    [Header("是否开启高性能模式")]
    public bool IsHighPerformance = false;


    void Start()
    {
        //m_MeshTemplet.DebugVertices();
        SurfaceMat = TemplteMesh.SurfaceMaterial;
        SectionMat = TemplteMesh.SectionMaterial;

    }

    public void InitData()
    {
        InitPathNodeList();
        InitBezierList();
    }

    public void ClearData() {

        if (PathRoot != null) m_PathList.Clear();
        if (PathRoot != null) m_BezierList.Clear();
    }

    private void InitPathNodeList()
    {
        if (PathRoot == null) m_PathList = new List<Transform>();
        m_PathList.Clear();
        m_CopyPosList.Clear();
        for (int i = 0; i < PathRoot.childCount; i++)
        {

            Transform node = PathRoot.GetChild(i);
            node.name = i+"";
            m_PathList.Add(node);
            m_CopyPosList.Add(node.position);
        }
    }

    private void InitBezierList() {
        if (m_BezierList == null) m_BezierList = new List<Transform>(); else {
            for (int i = 0; i < m_BezierList.Count; i++)
            {
                GameObject.DestroyImmediate(m_BezierList[i].gameObject);
            }
        }
        m_BezierList.Clear();
        for (int i = 0; i < m_PathList.Count - 1; i++) {
            GameObject bezierPoint = new GameObject("Bezier_" + i);
            bezierPoint.transform.parent = m_PathList[i];
            bezierPoint.transform.localPosition = (m_PathList[i + 1].position - m_PathList[i].position) / 2;
            m_BezierList.Add(bezierPoint.transform);
        }
    }

    public class Vertices {

        public int Index;

        public Vector3 Position;

        public Vertices(int Index, Vector3 Position) {
            this.Index = Index;
            this.Position = Position;
        }
    }

    public List<Vertices> DebugVerticeList = new List<Vertices>();
    List<Vector3> pathList = new List<Vector3>();
    List<Vector3> beizerList = new List<Vector3>();
    public void CreateAutoTunnel()
    {
        pathList.Clear();
        beizerList.Clear();
        m_PathList.ForEach((point)=> {
            pathList.Add(point.position);
        });
        //List<Vector3> beizerList = new List<Vector3>();
        m_BezierList.ForEach((point) => {
            beizerList.Add(point.position);
        });
        if (IsHighPerformance)
        {
            DateTime jbBeforDT = System.DateTime.Now;
            DynamicModelLibraryHP.DynamicSpwanModelWithHighPerformance(TemplteMesh, pathList, beizerList, (meshPlus, mats, textureTile) => {
                GameObject model = new GameObject(TemplteMesh.name);
                //model.transform.position = pathList[0];
                SpwanTunnelGB = model;
                MeshFilter mesh = model.AddComponent<MeshFilter>();
                mesh.mesh = meshPlus.MeshData;
                MeshRenderer render = model.AddComponent<MeshRenderer>();
                render.materials = mats;
                SpwanTunnelMesh = meshPlus;
                render.materials[0].SetVector("_MainTex_ST", textureTile);
            }, DynamicModelLibrary.TextureType.Texture, Segment);
            DateTime jbAfterDT = System.DateTime.Now;
            TimeSpan ts = jbAfterDT.Subtract(jbBeforDT);
            Debug.Log("高性能总共花费" + ts.TotalMilliseconds + "ms.  ");
        }
        else {
            DateTime jbBeforDT = System.DateTime.Now;
            DynamicModelLibrary.DynamicSpwanModel(TemplteMesh, pathList, beizerList, (meshPlus, mats, textureTile) => {
                GameObject model = new GameObject(TemplteMesh.name);
                //model.transform.position = pathList[0];
                SpwanTunnelGB = model;
                MeshFilter mesh = model.AddComponent<MeshFilter>();
                mesh.mesh = meshPlus.MeshData;
                MeshRenderer render = model.AddComponent<MeshRenderer>();
                render.materials = mats;
                SpwanTunnelMesh = meshPlus;
                render.materials[0].SetVector("_MainTex_ST", textureTile);
            }, DynamicModelLibrary.TextureType.Texture, Segment);
            DateTime jbAfterDT = System.DateTime.Now;
            TimeSpan ts = jbAfterDT.Subtract(jbBeforDT);
            Debug.Log("普通模式总共花费" + ts.TotalMilliseconds + "ms.  ");
        }
        System.GC.Collect();
        /*
        List<Vector3>  pathCureList = DynamicModelLibrary.TakeSimplesBezierPointList(pathList, beizerList,30);
        LineRenderer line = this.gameObject.AddComponent<LineRenderer>();
        line.positionCount = pathCureList.Count;
        line.material = TemplteMesh.SurfaceMaterial;
        line.SetPositions(pathCureList.ToArray());
        */
    }


    // Update is called once per frame
    void Update()
    {
        if (Input.GetKeyDown(KeyCode.P)) {
            CreateAutoTunnel();
        }
        //if (SpwanTunnelMesh != null)
        //{
        //    DynamicModelLibrary.DynamicSpwanRefreshModel(SpwanTunnelMesh, pathList, beizerList, () =>
        //    {

        //    });
        //}
        if (Input.GetKeyDown(KeyCode.R))
        {
            pathList.Clear();
            beizerList.Clear();
            m_PathList.ForEach((point) =>
            {
                pathList.Add(point.position);
            });
            //List<Vector3> beizerList = new List<Vector3>();
            m_BezierList.ForEach((point) =>
            {
                beizerList.Add(point.position);
            });
            DynamicModelLibrary.DynamicSpwanRefreshModel(SpwanTunnelMesh, pathList, beizerList, null);

        }
    }

    /// <summary>
    /// 自动计算贝塞尔曲线
    /// </summary>
    public void AutoCaculateBezierCure() {
        
        List<Vector3> pathList = new List<Vector3>();
        m_PathList.ForEach((point) => {
            pathList.Add(point.position);
        });
        List<Vector3> bezierPointList;
        switch (CurveModel) {
            case DynamicModelLibrary.CurveModel.NORMAL:
                bezierPointList = TheDarkKnight.DynamicSpwanModel.DynamicModelLibrary.AutoCaculateBezierCurve(pathList, true, DynamicModelLibrary.CurveModel.NORMAL, 0, 0);
                break;
            case DynamicModelLibrary.CurveModel.LASTONESIDE:
                bezierPointList = TheDarkKnight.DynamicSpwanModel.DynamicModelLibrary.AutoCaculateBezierCurve(pathList, true, DynamicModelLibrary.CurveModel.LASTONESIDE, 0, 0, LastGradient,NextGradient);
                break;
            case DynamicModelLibrary.CurveModel.NEXTONESIDE:
                bezierPointList = TheDarkKnight.DynamicSpwanModel.DynamicModelLibrary.AutoCaculateBezierCurve(pathList, true, DynamicModelLibrary.CurveModel.NEXTONESIDE, 0, 0, LastGradient, NextGradient);
                break;
            case DynamicModelLibrary.CurveModel.BOTHSIDE:
                bezierPointList = TheDarkKnight.DynamicSpwanModel.DynamicModelLibrary.AutoCaculateBezierCurve(pathList, true, DynamicModelLibrary.CurveModel.BOTHSIDE, 0, 0, LastGradient, NextGradient);
                break;
            default:
                bezierPointList = new List<Vector3>();
                break;
        }
        Vector3 startGradient;
        Vector3 endGradient;
        TheDarkKnight.DynamicSpwanModel.DynamicModelLibrary.CatchStartAndEndGradient(pathList, bezierPointList,out startGradient,out endGradient);

        Debug.Log("startGradient :" + startGradient);

        Debug.Log("endGradient : " + endGradient);

        for (int i = 0; i < bezierPointList.Count; i++)
        {
            m_BezierList[i].position = bezierPointList[i];
        }
        
    }


    public void ClearAllData() {
        m_PathList.Clear();
        for (int i = 0; i < m_BezierList.Count; i++)
        {
            if (m_BezierList[i] != null)
                GameObject.DestroyImmediate(m_BezierList[i].gameObject);
        }
        m_BezierList.Clear();
    }

    /// <summary>
    /// 二次贝塞尔
    /// </summary>
    public Vector3 BezierCurve(Vector3 startNode, Vector3 endNode, Vector3 bezierNode, float t)
    {
        return (1 - t) * (1 - t) * startNode + 2 * t * (1 - t) * bezierNode + t * t * endNode;
    }

    /// <summary>
    /// 二次贝塞尔斜率
    /// </summary>
    /// <param name="startNode"></param>
    /// <param name="endNode"></param>
    /// <param name="bezierNode"></param>
    /// <param name="t"></param>
    /// <returns></returns>
    public Vector3 BezierCurveGradient(Vector3 startNode, Vector3 endNode, Vector3 bezierNode, float t) {

        return (2 * startNode - 4 * bezierNode + 2 * endNode) * t + 2 * bezierNode - 2 * startNode;
    }

}
 